﻿using System;
using System.Diagnostics;
using System.IO;
using System.Text;
using System.Threading;
using System.Windows.Forms;
using System.Collections.Generic;
using System.Collections.ObjectModel;

namespace KaixinShell
{
    public partial class StartupForm : Form
    {
        private const int RICHTEXT_MAXLENGTH = 3000;
        //private const string TABNAME_N1 = "开心朋友买卖";
        //private const string TABNAME_N2 = "开心争车位";
        //private const string TABNAME_N3 = "开心咬人";
        //private const string TABNAME_N4 = "校内争车位";
        //private const string TABNAME_N5 = "校内宠物狗";
        //private const string TABNAME_N6 = "校内超级大亨";
        private string[] TABNAME_N8 = new string[] { "开心朋友买卖", "开心争车位", "开心咬人", "开心拉力赛", 
                                              "开心买房子", "校内争车位", "校内宠物狗", "校内超级大亨" };

        private Collection<String> displayTextList = new Collection<String>();
        private Collection<Process> processList = new Collection<Process>();
        //public delegate void ThreadDelegate(string strTab, int index);
        public delegate void ThreadDelegate(int index);

        public StartupForm()
        {
            InitializeComponent();
            //string[] loPageNames = new string[] { TABNAME_N1, TABNAME_N2, TABNAME_N3, TABNAME_N4, TABNAME_N5 };
            //AddTabPages(loPageNames.Length, loPageNames);
            AddTabPages(TABNAME_N8.Length, TABNAME_N8);
        }

        private void AddTabPages(int count, string[] pageNames)
        {
            tabControl1.Controls.Clear();
            for (int i=0; i<pageNames.Length; i++)
            {
                TabPage tabPage = new TabPage();
                StartupTabPageCtrl page = new StartupTabPageCtrl();
                tabPage.Controls.Add(page);

                tabPage.Name = "tabPage" + i.ToString();
                tabPage.Text = pageNames[i];
                page.Dock = System.Windows.Forms.DockStyle.Fill;
                page.btnBrowse1.Click += new System.EventHandler(this.btnBrowse_Click);
                page.btnStart1.Click += new System.EventHandler(this.btnStart_Click);
                page.btnStop1.Click += new System.EventHandler(this.btnStop_Click);
                page.timer1.Tick += new System.EventHandler(this.timer1_Tick);
                page.timer1.Tag = i.ToString();
                page.Tag = i.ToString();

                tabControl1.Controls.Add(tabPage);
                displayTextList.Add(String.Empty);
                processList.Add(null);
            }
        }

        public void OnBrowseClick()
        {
            OpenFileDialog openDlg = new OpenFileDialog();
            openDlg.Multiselect = false;
            openDlg.Filter = @"所有可执行文件(*.exe)|*.exe|所有文件(*.*)|*.*";
            openDlg.Title = @"打开可执行文件";
            if (openDlg.ShowDialog() == DialogResult.OK)
            {
                if (GetStartupTabPageCtrl() != null)
                    GetStartupTabPageCtrl().txtExecutable1.Text = openDlg.FileName;
            }
        }

        private StartupTabPageCtrl GetStartupTabPageCtrl()
        {
            return (StartupTabPageCtrl)tabControl1.SelectedTab.Controls[0];
        }

        private StartupTabPageCtrl GetStartupTabPageCtrl(int i)
        {
            return (StartupTabPageCtrl)tabControl1.Controls[i].Controls[0];
        }

        public void btnBrowse_Click(object sender, EventArgs e)
        {
            OnBrowseClick();
        }

        public void OnStartClick()
        {
            if (GetStartupTabPageCtrl() == null)
                return;

            GetStartupTabPageCtrl().txtResult1.Text = string.Empty;

            if (GetStartupTabPageCtrl().txtExecutable1.Text.Trim() != string.Empty)
            {
                try
                {
                    GetStartupTabPageCtrl().btnStart1.Enabled = false;
                    GetStartupTabPageCtrl().timer1.Enabled = true;

                    //Thread cmdThread = new Thread(new ThreadStart(OnThreadRun));
                    //cmdThread.Start();
                    ThreadDelegate td = new ThreadDelegate(OnThreadRun);
                    //td.BeginInvoke(tabControl1.SelectedTab.Text, tabControl1.SelectedIndex, null, null);
                    td.BeginInvoke(tabControl1.SelectedIndex, null, null);

                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
                finally
                {
                    GetStartupTabPageCtrl().btnStart1.Enabled = true;
                }
            }
            else
            {
                MessageBox.Show("请选择可执行文件.");
            }
        }

        private void OnThreadRun(int index)
        {
            if (GetStartupTabPageCtrl(index) == null)
                return;

            String strExecutable = String.Empty;
            String strParameter = String.Empty;

            strExecutable = GetStartupTabPageCtrl(index).txtExecutable1.Text.Trim();
            strParameter = GetStartupTabPageCtrl(index).txtParameter1.Text.Trim();

            // Create Process Start information
            ProcessStartInfo processStartInfo = new ProcessStartInfo(strExecutable, strParameter);
            processStartInfo.ErrorDialog = false;
            processStartInfo.UseShellExecute = false;
            processStartInfo.CreateNoWindow = true;

            //processStartInfo.RedirectStandardInput = true;
            processStartInfo.RedirectStandardOutput = true;
            processStartInfo.RedirectStandardError = true;

            // Execute the process
            Process loProcess = null;
            foreach (Process p in processList)
            {
                if (p != null && p.StartInfo.FileName == strExecutable && p.StartInfo.Arguments == strParameter)
                {
                    loProcess = p;
                    return;
                }
            }

            ProcessRun(ref loProcess, processStartInfo, index);
            GetStartupTabPageCtrl(index).timer1.Enabled = false;
        }

        private void ProcessRun(ref Process process, ProcessStartInfo processStartInfo, int index)
        {
            process = new Process();
            process.StartInfo = processStartInfo;
            bool processStarted = process.Start();

            if (processStarted)
            {
                int id = Convert.ToInt32(GetStartupTabPageCtrl(index).Tag);
                processList[id] = process;

                // Set our event handler to asynchronously read the command output.
                process.OutputDataReceived += new DataReceivedEventHandler(OnCmdOutputHandler);
                process.ErrorDataReceived += new DataReceivedEventHandler(OnCmdErrorHandler);

                // Start the asynchronous read of the command output stream.
                process.BeginOutputReadLine();
                process.BeginErrorReadLine();
                process.WaitForExit();
            }

            process.Close();
            process.Dispose();
            process = null;
        }

        private void btnStart_Click(object sender, EventArgs e)
        {
            OnStartClick();
        }

        private void OnCmdOutputHandler(object sendingProcess, DataReceivedEventArgs outLine)
        {
            // Collect the console window's command output.
            if (!String.IsNullOrEmpty(outLine.Data))
            {
                // Add the text to the collected output.
                for (int i = 0; i < processList.Count; i++)
                {
                    if (sendingProcess.Equals(processList[i]))
                    {
                        //displayText.Append(Environment.NewLine + outLine.Data);
                        displayTextList[i] += Environment.NewLine + outLine.Data;
                    }
                }
            }
        }

        private void OnCmdErrorHandler(object sendingProcess, DataReceivedEventArgs outLine)
        {
            // Collect the console window's command error.
            if (!String.IsNullOrEmpty(outLine.Data))
            {
                // Add the text to the collected output.
                for (int i = 0; i < processList.Count; i++)
                {
                    if (sendingProcess.Equals(processList[i]))
                    {
                        //displayText.Append(Environment.NewLine + outLine.Data);
                        displayTextList[i] += Environment.NewLine + outLine.Data;
                    }
                }
            }
        }

        private void timer1_Tick(object sender, EventArgs e)
        {
            System.Windows.Forms.Timer t = (System.Windows.Forms.Timer)sender;
            int i = Convert.ToInt32(t.Tag);

            if (!String.IsNullOrEmpty(displayTextList[i].ToString()))
            {
                StartupTabPageCtrl page = GetStartupTabPageCtrl(i);
                if (page.txtResult1.Lines.Length > RICHTEXT_MAXLENGTH)
                    page.txtResult1.Text = String.Empty;

                page.txtResult1.Text += displayTextList[i].ToString();
                displayTextList[i] = String.Empty;
                //this.Invalidate();
                page.txtResult1.SelectionStart = page.txtResult1.Text.Length;
            }
        }

        private void ProcessClose(Process process)
        {
            if (process != null)
            {
                process.CancelOutputRead();
                try
                {
                    if (process.CloseMainWindow())
                        process.Close();
                    else
                        process.Kill();
                }
                catch (InvalidOperationException)
                {
                }
                catch (Exception ex)
                {
                    MessageBox.Show(ex.Message);
                }
            }
        }

        private void OnStopClick()
        {
            StartupTabPageCtrl page = GetStartupTabPageCtrl();
            int i = Convert.ToInt32(page.Tag);
            if (i < processList.Count)
            {
                ProcessClose(processList[i]);
                processList[i] = null;
            }
        }

        private void btnStop_Click(object sender, EventArgs e)
        {
            OnStopClick();
        }

        /// <summary>
        /// This is the notify Icon double click event when you click the tray icon
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void notifyIcon1_DoubleClick(object sender, EventArgs e)
        {
            if (this.WindowState == FormWindowState.Minimized)
            {
                this.Show();
                this.WindowState = FormWindowState.Normal;
            }

            // Activate the form.
            this.Activate();
            this.Focus();
        }

        /// <summary>
        /// This is the context menu for the notify icon
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void exitToolStripMenuItem_Click(object sender, EventArgs e)
        {
            //If we don't minimize the window first we won't be able to close the window.
            this.WindowState = FormWindowState.Minimized;
            Close();
        }

        /// <summary>
        /// This is the form move event.  We are causing the form to not show up on the
        /// task bar when minimized.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void StartupForm_Move(object sender, EventArgs e)
        {
            //This code causes the form to not show up on the task bar only in the tray.
            //NOTE there is now a form property that will allow you to keep the application
            //from every showing up in the task bar.
            if (this == null)
            { //This happen on create.
                return;
            }
            //If we are minimizing the form then hide it so it doesn't show up on the task bar
            if (this.WindowState == FormWindowState.Minimized)
            {
                this.Hide();
                notifyIcon1.ShowBalloonTip(3000);
            }
            else
            {//any other windows state show it.
                this.Show();
            }
        }

        /// <summary>
        /// This is the form closing event.  You have the opportunity to keep the form
        /// from closing here.
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void StartupForm_FormClosing(object sender, FormClosingEventArgs e)
        {
            ////There are several ways to close an application.
            ////We are trying to find the click of the X in the upper right hand corner
            ////We will only allow the closing of this app if it is minized.
            //if (this.WindowState != FormWindowState.Minimized)
            //{
            //    //we don't close the app...
            //    e.Cancel = true;
            //    //minimize the app and then display a message to the user so
            //    //they understand they didn't close the app they just sent it to the tray.
            //    this.WindowState = FormWindowState.Minimized;
            //    //Show the message.
            //    notifyIcon1.ShowBalloonTip(3000, "Test App",
            //        "You have not closed this appliation." +
            //        (Char)(13) + "It has be moved to the tray." +
            //        (Char)(13) + "Right click the Icon to exit.",
            //        ToolTipIcon.Info);
            //}
            foreach (Process p in processList)
                ProcessClose(p);
        }
    }
}
